package com.yuanda.erp9.syn.schedule;

import com.alibaba.fastjson.JSON;
import com.innovation.ic.b1b.framework.util.StringUtils;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yuanda.erp9.syn.StockPriceMonitor.ErpServer;
import com.yuanda.erp9.syn.StockPriceMonitor.Request.ErpPushInquiryPriceRequest;
import com.yuanda.erp9.syn.StockPriceMonitor.Response.ErpLoginResponse;
import com.yuanda.erp9.syn.StockPriceMonitor.Response.ErpPushInquiryPriceResponse;
import com.yuanda.erp9.syn.StockPriceMonitor.Response.RatioResponse;
import com.yuanda.erp9.syn.annotation.EnablePriceWarn;
import com.yuanda.erp9.syn.entity.PushErpInquiryPriceRecordEntity;
import com.yuanda.erp9.syn.entity.dyj_middledata.DyjInstorageByPriceEntity;
import com.yuanda.erp9.syn.entity.dyj_middledata.DyjInstorageByYJPriceEntity;
import com.yuanda.erp9.syn.enums.CurrencyEnum;
import com.yuanda.erp9.syn.enums.ErpCurrencyEnum;
import com.yuanda.erp9.syn.enums.PushErpStatusEnum;
import com.yuanda.erp9.syn.enums.SourceEnum;
import com.yuanda.erp9.syn.pojo.CmsPricesPojo;
import com.yuanda.erp9.syn.service.dyj_middledata.DyjInstorageByPriceService;
import com.yuanda.erp9.syn.service.dyj_middledata.DyjInstorageByYJPriceService;
import com.yuanda.erp9.syn.service.erp9.CmsSuppliersTempService;
import com.yuanda.erp9.syn.service.erp9.ESService;
import com.yuanda.erp9.syn.service.erp9.PushErpInquiryPriceRecordService;
import com.yuanda.erp9.syn.service.erp9_pvecrm.QuoteForStockMonitorTopViewService;
import com.yuanda.erp9.syn.service.erp9_pvestandard.PetNamesService;
import com.yuanda.erp9.syn.vo.EsCmsGoodsVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zengqinglong
 * @desc 库存价格预警
 * @Date 2023/4/6 13:07
 **/
@Component
public class ErpStockPriceMonitorTask {
    private static final String PATTERN = "yyyy-MM-dd";
    private static final String PATTERN_BATCH = "yy";

    public static SimpleDateFormat simpleFormat = new SimpleDateFormat(PATTERN);
    public static SimpleDateFormat simpleFormatBATCH = new SimpleDateFormat(PATTERN_BATCH);

    @Resource
    private QuoteForStockMonitorTopViewService quoteForStockMonitorTopViewService;

    @Resource
    private ErpServer erpServer;

    @Resource
    private ESService esService;

    @Resource
    private PushErpInquiryPriceRecordService pushErpInquiryPriceRecordService;

    @Resource
    private CmsSuppliersTempService cmsSuppliersTempService;

    @Resource
    private DyjInstorageByPriceService dyjInstorageByPriceService;

    @Resource
    private DyjInstorageByYJPriceService dyjInstorageByYJPriceService;

    @Resource
    private PetNamesService petNamesService;

    private static final Logger log = LoggerFactory.getLogger(ErpStockPriceMonitorTask.class);
    // 供应商名称
    private static final String SUPPLIER = "Cycle-chips Components Inc.";
    // 供应商id
    private static final String SUPPLIER_ID = "US000008311";

    /**
     * 测试 和 生产 只能选一个环境不能同时（大赢家就提供一个库）
     * 库存价格预警 （每天晚上9点执行）
     */
    @XxlJob("StockMonitorJob")
    @EnablePriceWarn
    public void StockMonitor() {
        long l = System.currentTimeMillis();
        //需要在本地留痕的列表
        List<PushErpInquiryPriceRecordEntity> insertPushErp = new ArrayList<>();
        //需要更新本地留痕的列表
        List<PushErpInquiryPriceRecordEntity> updatePushErp = new ArrayList<>();
        //需要添加到大赢家提供的数据库列表
        List<DyjInstorageByYJPriceEntity> insertDate = new ArrayList<>();

        List<DyjInstorageByPriceEntity> dyjInstorageByPriceEntityList = new ArrayList<>();
        try {
            log.info("库存价格预警 开始");
            //获取当天的汇率
            RatioResponse ratio = erpServer.getRatio();
            if (ratio.getData() == null) {
                log.info("库存价格预警 获取当天汇率失败");
                return;
            }
            BigDecimal rate = ratio.getData().getRate();

            //1.获取大赢家提供的型号表
            dyjInstorageByPriceEntityList = dyjInstorageByPriceService.findAll();
            log.info("获取大赢家提供的型号表 数量:{}", dyjInstorageByPriceEntityList.size());
            //获取当天时间
            Date date = new Date();
            //无效数量
            int invalidCount = 0;
            //2.遍历型号表
            for (DyjInstorageByPriceEntity dyjInstorageByPriceEntity : dyjInstorageByPriceEntityList) {
                //2-1.查询对应erp视图表获取价格 首先获取14天内的数据
                //2023-05-16 修改取数规则
                //1.优先询报价7天的数据>询报价14天数据>icgo
                //2.icgo取值：批号3年内的取中位数，数量>=10
                BigDecimal price = getErpQuoteForStockMonitorTopView(dyjInstorageByPriceEntity.getModel(), getDateFromString(date, 13, true), simpleFormat.format(date), rate,simpleFormat);

                //2-3.erp视图和ICGoo没有 就需要查询14天内有效的erp数据
                //2-3.erp视图 查询14天内有效的erp数据
//                if (price == null) {
//                    price = getErpQuoteForStockMonitorTopView(dyjInstorageByPriceEntity.getModel(), getDateFromString(date, 13, true), simpleFormat.format(date), rate);
//                }

                //2-2.如果查询erp视图7天内为空就需要查询ICGoo供应商里的价格
                if (price == null) {
                    price = getICGooPrice(dyjInstorageByPriceEntity.getModel(), rate);
                }

                //2-4.已上三种都未能满足 需要推送erp,14天内无需重复推送
                if (price == null) {
                    //品牌为空的不推送
                    if (StringUtils.isEmpty(dyjInstorageByPriceEntity.getManufactor())) {
                        invalidCount ++;
                        continue;
                    }
                    //转换品牌
                    List<String> brands = petNamesService.conversionStandardNameByBrand(dyjInstorageByPriceEntity.getManufactor());
                    //品牌转换不了成标准库的品牌就不推送（产品需求）
                    if (CollectionUtils.isEmpty(brands)) {
                        invalidCount ++;
                        continue;
                    }
                    PushErpInquiryPriceRecordEntity pushErpInquiryPriceRecordEntity = new PushErpInquiryPriceRecordEntity();
                    pushErpInquiryPriceRecordEntity.setBrand(brands.get(0));
                    pushErpInquiryPriceRecordEntity.setModel(dyjInstorageByPriceEntity.getModel());
                    pushErpInquiryPriceRecordEntity.setCreateTime(date);
                    pushErpInquiryPriceRecordEntity.setUpdateTime(date);
                    pushErpInquiryPriceRecordEntity.setStatus(PushErpStatusEnum.TO_BE_PUSH.getStatus());
                    List<PushErpInquiryPriceRecordEntity> byPartNumberList = pushErpInquiryPriceRecordService.findByPartNumber(pushErpInquiryPriceRecordEntity);
                    if (CollectionUtils.isEmpty(byPartNumberList)) {
                        //新增推送记录列表
                        insertPushErp.add(pushErpInquiryPriceRecordEntity);
                    } else {
                        if (isNeedPush(byPartNumberList.get(0).getCreateTime(), date)) {
                            //更新时间
                            byPartNumberList.get(0).setCreateTime(date);
                            byPartNumberList.get(0).setUpdateTime(date);
                            //更新状态
                            byPartNumberList.get(0).setStatus(PushErpStatusEnum.TO_BE_PUSH.getStatus());
                            //更新推送记录列表
                            updatePushErp.add(byPartNumberList.get(0));
                        }
                    }
                    continue;
                }

                //添加到保存到大赢家列表
                DyjInstorageByYJPriceEntity dyjInstorageByYJPriceEntity = new DyjInstorageByYJPriceEntity();
                if (StringUtils.isNotEmpty(dyjInstorageByPriceEntity.getManufactor())) {
                    dyjInstorageByYJPriceEntity.setManufactor(dyjInstorageByPriceEntity.getManufactor());
                }
                dyjInstorageByYJPriceEntity.setModel(dyjInstorageByPriceEntity.getModel());
                dyjInstorageByYJPriceEntity.setPrice(price.setScale(4, BigDecimal.ROUND_UP));
                dyjInstorageByYJPriceEntity.setCreatDate(date);
                insertDate.add(dyjInstorageByYJPriceEntity);
            }

            //3.批量插入到大赢家提供的数据库
            if (!CollectionUtils.isEmpty(insertDate)) {
                dyjInsertDate(insertDate);
                insertDate.clear();
            }

            //4.保存推送数据到本地（保证不能报错，报错需要临时执行定时任务）
            if (!CollectionUtils.isEmpty(insertPushErp)) {
                log.info("库存价格预警 批量保存推送数据,数量:{}", insertPushErp.size());
                pushErpInquiryPriceRecordService.batchInsert(insertPushErp);
                insertPushErp.clear();
            }

            //5.更新推送数据到本地（保证不能报错，报错需要临时执行定时任务）
            if (!CollectionUtils.isEmpty(updatePushErp)) {
                log.info("库存价格预警 批量保更新推送数据,数量:{}", updatePushErp.size());
                pushErpInquiryPriceRecordService.batchUpdate(updatePushErp);
                updatePushErp.clear();
            }
            log.info("库存价格预警 无效数量:{}", invalidCount);
            //6.推送数据到erp（报错，通过定时任务重新发送）
            pushErp();
            log.info("库存价格预警 结束 耗时:{}ms ", System.currentTimeMillis() - l);
        } catch (Exception e) {
            log.error("执行 库存价格预警 定时任务失败,e:{}", e);
        } finally {
            dyjInstorageByPriceEntityList.clear();
            insertPushErp.clear();
            updatePushErp.clear();
            insertDate.clear();
        }
    }

    /**
     * 批量插入大赢家所需数据 分批每1000条插入
     *
     * @param insertDate
     */
    public void dyjInsertDate(List<DyjInstorageByYJPriceEntity> insertDate) {
        log.info(" 批量插入大赢家所需数据 分批每100条插入 开始，数量:{}", insertDate.size());
        //每次批量插入100条
        List<DyjInstorageByYJPriceEntity> dyjInsertDate = new ArrayList<>();
        for (DyjInstorageByYJPriceEntity dyjInstorageByYJPriceEntity : insertDate) {
            dyjInsertDate.add(dyjInstorageByYJPriceEntity);
            if (dyjInsertDate.size() == 100) {
                dyjInstorageByYJPriceService.batchInsert(dyjInsertDate);
                dyjInsertDate.clear();
            }
        }

        if (dyjInsertDate.size() > 0) {
            dyjInstorageByYJPriceService.batchInsert(dyjInsertDate);
            dyjInsertDate.clear();
        }
        log.info("批量插入大赢家所需数据 分批每1000条插入 结束，数量:{}", insertDate.size());
    }

    /**
     * 推送erp
     */
    public void pushErp() {
        try {
            log.info("推送erp数据 开始");
            //查询没有推送erp的记录
            List<PushErpInquiryPriceRecordEntity> pushErpInquiryPriceRecordEntities = pushErpInquiryPriceRecordService.findByStatus();
            //没有推送记录无需处理
            if (CollectionUtils.isEmpty(pushErpInquiryPriceRecordEntities)) {
                return;
            }
            //获取登陆token
            ErpLoginResponse erpLoginResponse = erpServer.ErpLogin();

            if (!erpLoginResponse.isSuccess()) {
                log.info("推送erp数据 结束 获取登陆token失败,未能推送询价记录");
                return;
            }
            //封装推送询价记录 并推送
            List<Integer> ids = new ArrayList<>();
            List<ErpPushInquiryPriceRequest.Inquirys> pushList = new ArrayList<>();


            //设置请求参数
            ErpPushInquiryPriceRequest erpPushInquiryPriceRequest = new ErpPushInquiryPriceRequest();
            //todo 由张斌提供 客户id ID=Ep2305120010&SiteID=Sites230512000041-001
            erpPushInquiryPriceRequest.setClientID("Sites230512000041-001");
            //固定发货地 大陆
            erpPushInquiryPriceRequest.setDistrict("FArea01");
            erpPushInquiryPriceRequest.setSource(3);
            //固定币种 人民币
            erpPushInquiryPriceRequest.setCurrency(ErpCurrencyEnum.CNY.getCode());
            erpPushInquiryPriceRequest.setInvoiceType(4);
            erpPushInquiryPriceRequest.setInvoiceMethod(1);

            for (PushErpInquiryPriceRecordEntity pushErpInquiryPriceRecordEntity : pushErpInquiryPriceRecordEntities) {
                ids.add(pushErpInquiryPriceRecordEntity.getId());
                pushList.add(pushErpInquiryPriceRecordEntityToInquirys(pushErpInquiryPriceRecordEntity));
                //询价最大300条
                if (pushList.size() == 300) {
                    erpPushInquiryPriceRequest.setInquirys(pushList);
                    ErpPushInquiryPriceResponse erpPushInquiryPriceResponse = erpServer.pushInquiryPriceRequest(erpPushInquiryPriceRequest, erpLoginResponse.getToken());
                    //根据返回值修改对应的值
                    if (erpPushInquiryPriceResponse.isSuccess()) {
                        pushErpInquiryPriceRecordService.updateStatusAndInquiryNumberByIds(ids, erpPushInquiryPriceResponse.getData());
                    }
                    //清空处理 防止下面操作误更改
                    ids.clear();
                    //清空处理防止下面操作误更改
                    pushList.clear();
                }
            }

            if (pushList.size() > 0) {
                erpPushInquiryPriceRequest.setInquirys(pushList);
                ErpPushInquiryPriceResponse erpPushInquiryPriceResponse = erpServer.pushInquiryPriceRequest(erpPushInquiryPriceRequest, erpLoginResponse.getToken());
                //根据返回值修改对应的值
                if (erpPushInquiryPriceResponse.isSuccess()) {
                    pushErpInquiryPriceRecordService.updateStatusAndInquiryNumberByIds(ids, erpPushInquiryPriceResponse.getData());
                }
                //清空处理 防止误更改
                ids.clear();
                pushList.clear();
            }
            log.info("推送erp数据 结束");
        } catch (Exception e) {
            log.info("推送erp异常 e:{}", e);
        }
    }

    /**
     * 转换erp推送实体
     *
     * @param pushErpInquiryPriceRecordEntity
     * @return
     */
    public ErpPushInquiryPriceRequest.Inquirys pushErpInquiryPriceRecordEntityToInquirys(PushErpInquiryPriceRecordEntity pushErpInquiryPriceRecordEntity) {
        ErpPushInquiryPriceRequest.Inquirys inquirys = new ErpPushInquiryPriceRequest.Inquirys();
        inquirys.setPartNumber(pushErpInquiryPriceRecordEntity.getModel());
        inquirys.setBrand(pushErpInquiryPriceRecordEntity.getBrand());
        //固定1000
        inquirys.setQuantity(1000);
        //todo 由陈瀚或董健提供 销售warning
        inquirys.setSalerID("A00471");
        //交货日期
        inquirys.setDeliveryDate(getDateFromString(new Date(), 14, false));
        //购货性质
        inquirys.setNature(1);
        //不走代理
        inquirys.setIsAgent(false);
        //询价类型为1
        inquirys.setInquiryOrderType(1);
        return inquirys;
    }

    /**
     * 获取icgoo的价格
     *
     * @param partNumber
     * @param rate
     * @return
     */
    public BigDecimal getICGooPrice(String partNumber, BigDecimal rate) {
        Integer supplierId = cmsSuppliersTempService.getSupplierIdByUs(SUPPLIER, SUPPLIER_ID);
        List<EsCmsGoodsVo> goodsBySupplierIdAndModelAndSource = esService.findGoodsBySupplierIdAndModelAndSource(supplierId, partNumber, SourceEnum.DATA_PACKAGE.getCode());
        //判断是否有数据
        if (CollectionUtils.isEmpty(goodsBySupplierIdAndModelAndSource)) {
            return null;
        }

        //规则改成
//        EsCmsGoodsVo esCmsGoodsVo = goodsBySupplierIdAndModelAndSource.get(0);
//        //判断第一条数据是否有阶梯价格
//        if (StringUtils.isEmpty(esCmsGoodsVo.getPrices())) {
//            return BigDecimal.valueOf(esCmsGoodsVo.getUnit_price());
//        }
//        List<CmsPricesPojo> cmsPricesPojos = JSON.parseArray(esCmsGoodsVo.getPrices(), CmsPricesPojo.class);
//        //转换阶梯价格
//        if (CollectionUtils.isEmpty(cmsPricesPojos)) {
//            return null;
//        }
//        //获取第一个阶梯价格算单价
//        CmsPricesPojo cmsPricesPojo = cmsPricesPojos.get(0);
//        //判断是否是人民币
//        if (cmsPricesPojo.getCurrency().equals(CurrencyEnum.RMB.getCode())) {
//            return cmsPricesPojo.getPrice();
//        }
//        //美元需要转换成人民币 同时需要在价格上 5%的点数
//        BigDecimal price = cmsPricesPojo.getPrice().multiply(rate);
//        price = price.add(price.multiply(BigDecimal.valueOf(0.05)));
//        return price;

        //库存大于10 价格排序的中位价格
        ArrayList<BigDecimal> bigDecimals = new ArrayList<>();
        for (EsCmsGoodsVo esCmsGoodsVo : goodsBySupplierIdAndModelAndSource) {
            //判断返回的
            if (esCmsGoodsVo.getRepertory() > 10 && isBatchMatchingAvailable(esCmsGoodsVo) && StringUtils.isNotEmpty(esCmsGoodsVo.getPrices())){
                List<CmsPricesPojo> cmsPricesPojos = JSON.parseArray(esCmsGoodsVo.getPrices(), CmsPricesPojo.class);
                for (CmsPricesPojo cmsPricesPojo : cmsPricesPojos) {
                    //判断是否是人民币
                    if (cmsPricesPojo.getCurrency().equals(CurrencyEnum.RMB.getCode())) {
                        bigDecimals.add(cmsPricesPojo.getPrice());
                    }else {
                        //美元需要转换成人民币 同时需要在价格上 5%的点数
                        BigDecimal price = cmsPricesPojo.getPrice().multiply(rate);
                        bigDecimals.add(price.add(price.multiply(BigDecimal.valueOf(0.05))));
                    }
                }
            }
        }

        //没有符合的价格
        if (CollectionUtils.isEmpty(bigDecimals)){
            return null;
        }
        //排序
        Collections.sort(bigDecimals);

        //计算中位数
        return bigDecimals.get((bigDecimals.size()-1)/2);
    }
    /**
     * 根据批次匹配是否可用（批次需要3年内的）
     */
    public static Boolean isBatchMatchingAvailable(EsCmsGoodsVo esCmsGoodsVo){
        //判断是不是为空 为空返回true
        if (StringUtils.isEmpty(esCmsGoodsVo.getBatch())){
            return true;
        }

        String batch = simpleFormatBATCH.format(new Date());
        Integer integer = Integer.valueOf(batch);
        for (int i = 0; i < 3; i++) {
            if (esCmsGoodsVo.getBatch().startsWith((integer-i)+"")){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取视图提供的价格
     *
     * @param partNumber
     * @param startDate
     * @param endDate
     * @param rate
     * @return
     */
    public BigDecimal getErpQuoteForStockMonitorTopView(String partNumber, String startDate, String endDate, BigDecimal rate,SimpleDateFormat simpleFormat) {
        return quoteForStockMonitorTopViewService.findByParNumberAndDate(partNumber, startDate, endDate, rate,simpleFormat);
    }

    /**
     * 是否需要推送
     *
     * @param pushDate 推送erp的时间
     * @param newDate  当天时间
     * @return
     */
    public boolean isNeedPush(Date pushDate, Date newDate) throws ParseException {
        //推送时间是第15天才需要重新推送
        String endDate = getDateFromString(pushDate, 14, false);
        return simpleFormat.parse(endDate).before(newDate);
    }

    /**
     * 转换截止时间
     *
     * @param date   时间
     * @param amount 天数
     * @param symbol true取时间前的天数 false取时间后的天数
     * @return
     */
    public  String getDateFromString(Date date, Integer amount, Boolean symbol) {
        Calendar cal = Calendar.getInstance();
        //获取前面的时间用-负号
        cal.setTime(date);
        if (symbol) {
            cal.add(Calendar.DAY_OF_MONTH, -amount);
        } else {
            cal.add(Calendar.DAY_OF_MONTH, amount);
        }
        return simpleFormat.format(cal.getTime());
    }

    /**
     * 转换截止时间
     *
     * @param date   时间
     * @param amount 天数
     * @param symbol true取时间前的天数 false取时间后的天数
     * @return
     */
    public Date getDateFormDate(Date date, Integer amount, Boolean symbol) {
        Calendar cal = Calendar.getInstance();
        //获取前面的时间用-负号
        cal.setTime(date);
        if (symbol) {
            cal.add(Calendar.DAY_OF_MONTH, -amount);
        } else {
            cal.add(Calendar.DAY_OF_MONTH, amount);
        }
        return cal.getTime();
    }
}
